//---------------------------------------------------------------------------

#ifndef ListaH
#define ListaH

#include "Nodo.h"
#include <stdlib>

//---------------------------------------------------------------------------
template <class T> class Lista{
private:
   Nodo<T>* primero;
   Nodo<T>* actual;
   Nodo<T>* saved;

   int longitud;

public:
   Lista();
   ~Lista();
   void inicia();
   void avanza();
   void retrocede();
   T* getActual();
   bool vacia();
   bool final();
   void inserta(T*);
   void insertaDespues(T*);
   void insertaAntes(T*);
   void eliminaActual();
   int getLongitud();
   void irAlFinal();
   T* get(int i);
   T* getUltimo();
   void savePosition();
   void restorePosition();
};

template <class T> Lista<T>::Lista(){
  primero=NULL;
  actual=NULL;
  longitud= 0;
}
template <class T> Lista<T>::~Lista(){
  Nodo<T>* r= primero;
  Nodo<T>* aux;
  while(r!=NULL){
    aux= r->getSig();
    delete r;
    r= aux;
  }
}
template <class T> void Lista<T>::inicia(){
  actual=primero;
}
template <class T> T* Lista<T>::getActual(){
  if(actual==NULL) return NULL;
  else return actual->getInf();
}
template <class T> void Lista<T>::avanza(){
  if(actual!=NULL) actual= actual->getSig();

}
template <class T> void Lista<T>::retrocede(){
  if(actual!=NULL) actual= actual->getAnt();

}
template <class T> bool Lista<T>::vacia(){
  return primero==NULL;
}
template <class T> bool Lista<T>::final(){
  return actual==NULL;
}
template <class T> void Lista<T>::inserta(T* t){
  if(vacia()){
    primero= new Nodo<T>(t, NULL, NULL);
    actual=primero;
  }
  else{
    Nodo<T>* aux= primero;
    primero= new Nodo<T>(t, aux, NULL);
    aux->setAnt(primero);
  }
  longitud++;
}


template <class T> void Lista<T>::eliminaActual(){
  if(actual!=NULL){
    if(actual->getSig()!=NULL)
       actual->getSig()->setAnt(actual->getAnt());
    if(actual->getAnt()!=NULL)
       actual->getAnt()->setSig(actual->getSig());

    if(actual==primero) primero= primero->getSig();
    Nodo<T>* aux= actual->getSig();
    delete actual;
    actual= aux;
    longitud--;
  }
}
template <class T> int Lista<T>::getLongitud(){
  return longitud;
}

template <class T> T* Lista<T>::getUltimo(){
        if (actual==NULL) actual = primero;
        while (!actual->getSig()==NULL)
                actual = actual->getSig();
        return actual->getInf();
};

template <class T> void Lista<T>::irAlFinal(){
        while (!final())
                actual = actual->getSig();
};

template <class T> T* Lista<T>::get(int i){
        inicia();
        for (int j=0; j<i; j++)
                avanza();
        return actual->getInf();
};

template <class T> void Lista<T>::insertaDespues(T* t)   {
        if (vacia()){
                primero= new Nodo<T>(t, NULL, NULL);
                actual=primero;
        }
        else {
                Nodo<T>* nodeAux = new Nodo<T>(t, actual->getSig(), actual );
                if (actual->getSig()!=NULL)
                        actual->getSig()->setAnt(nodeAux);
                actual->setSig( nodeAux ) ;
                actual = nodeAux;
        }
        longitud++;
}

template <class T> void Lista<T>::insertaAntes(T* t)   {
        if (vacia()){
                primero= new Nodo<T>(t, NULL, NULL);
                actual=primero;
        }
        else {
                Nodo<T>* nodeAux = new Nodo<T>(t, actual->getAnt(), actual );
                if (actual->getAnt()!=NULL)
                        actual->getAnt()->setSig(nodeAux);
                actual->setAnt( nodeAux ) ;
                actual = nodeAux;
        }
        longitud++;
}

template <class T> void Lista<T>::savePosition() {
        saved = actual;
};
template <class T> void Lista<T>::restorePosition() {
        actual = saved;
};



#endif
